package com.xbongbong.paas.script.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasMenuEntity;
import com.xbongbong.paas.domain.entity.ext.PaasAttachmentEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.MenuTypeEnum;
import com.xbongbong.paas.model.PaasMenuModel;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.XbbResponse;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.XbbProConstant;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.menu.enums.CRMMenuEnum;
import com.xbongbong.pro.script.pojo.dto.ProductDTO;
import com.xbongbong.pro.script.pojo.vo.ScriptVO;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.CabinetFileEntity;
import com.xbongbong.saas.domain.entity.KnowledgeBaseEntity;
import com.xbongbong.saas.domain.entity.KnowledgeDataEntity;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.help.KnowledgeBaseHelp;
import com.xbongbong.saas.model.CabinetFileModel;
import com.xbongbong.saas.model.KnowledgeBaseModel;
import com.xbongbong.saas.model.KnowledgeDataModel;
import com.xbongbong.sys.model.CompanyModel;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 知识库菜单脚本
 *
 * @author ruansicheng
 * @date 2022/07/7 18:32
 */
@RestController
@RequestMapping(XbbProConstant.API_ROOT_PREFIX + "/script/knowledge")
public class KnowledgeMenuController {
    private static final Logger LOG = LoggerFactory.getLogger(KnowledgeMenuController.class);
    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private CompanyModel companyModel;
    @Resource
    private PaasMenuModel paasMenuModel;
    @Resource
    private KnowledgeBaseHelp knowledgeBaseHelp;
    @Resource
    private KnowledgeBaseModel knowledgeBaseModel;
    @Resource
    private KnowledgeDataModel knowledgeDataModel;
    @Resource
    private CabinetFileModel cabinetFileModel;



    @RequestMapping(value = "/addMenu", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String addMenu(@RequestBody @Valid ProductDTO productDTO, BindingResult bindingResult) throws XbbException {
        XbbResponse<ScriptVO> response;
        if (!proBaseConfig.getXbbCode().equals(productDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        if (bindingResult.hasErrors()) {
            String errMsg = Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            LOG.warn("----------------开始刷老公司知识库菜单 -------------------");
            long start = DateTimeUtil.getInt();
            // 成功数
            Integer successNum = 0;
            // 如果没传公司ID就取所有公司
            List<String> corpidList = CollectionUtils.isNotEmpty(productDTO.getCorpidList()) ? productDTO.getCorpidList() : companyModel.getCorpidList();
            int i = 1;
            //更新失败公司ID集合
            Set<String> errorCorpidList = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            //别名集合
            List<String> aliasList = new ArrayList<>();
            aliasList.add(CRMMenuEnum.CONTRACT.getAlias());
            aliasList.add(CRMMenuEnum.KNOWLEDGE_BASE.getAlias());
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<String, Object> paramMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("aliasIn", aliasList);
            params.put("groupByStr", "alias");
            params.put("del", DelEnum.NORMAL.getDel());
            params.put("distributorMark",0);
            //插入菜单list
            List<PaasMenuEntity> paasMenuEntities = new ArrayList<>();
            for (String corpid : corpidList) {
                int x = corpidList.size() - i;
                LOG.info("-----------------------------当前是第" + i + "家公司,还有" + x + "家是公司需要刷--------------------------");
                i++;
                try {
                    //根据alias和coprid，查询菜单信息
                    params.put("corpid", corpid);
                    List<PaasMenuEntity> paasMenuEntityList = paasMenuModel.list(params);
                    //如果没有菜单，代表没有CRM
                    if (CollectionsUtil.isEmpty(paasMenuEntityList)) {
                        continue;
                    }
                    //如果已经生成过菜单
                    if (paasMenuEntityList.size() == 2) {
                        continue;
                    }
                    //获取菜单数量
                    paramMap.put("corpid", corpid);
                    paramMap.put("orderByStr", "sort DESC ");
                    Integer count = paasMenuModel.getEntitysCount(paramMap);
                    if (count == null) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.MENU_NOT_EXIST);
                    }
                    //将表单信息赋值给对应的菜单
                    for (PaasMenuEntity paasMenuEntity : paasMenuEntityList) {
                        PaasMenuEntity paasMenu;
                        if (Objects.equals(paasMenuEntity.getAlias(), CRMMenuEnum.CONTRACT.getAlias())) {
                            paasMenu = setDefaultValue(paasMenuEntity);
                            count = count + 1;
                            paasMenu.setSort(count);
                            paasMenu.setName(CRMMenuEnum.KNOWLEDGE_BASE.getName());
                            paasMenu.setAlias(CRMMenuEnum.KNOWLEDGE_BASE.getAlias());
                            paasMenu.setUrl(CRMMenuEnum.KNOWLEDGE_BASE.getAccessLinkEnum().getUrl());
                            paasMenu.setMobileUrl(CRMMenuEnum.KNOWLEDGE_BASE.getAccessLinkEnum().getMobileUrl());
                            paasMenu.setColor(CRMMenuEnum.KNOWLEDGE_BASE.getAccessLinkEnum().getColor());
                            paasMenu.setIcon(CRMMenuEnum.KNOWLEDGE_BASE.getAccessLinkEnum().getIcon());
                            paasMenuEntities.add(paasMenu);
                            break;
                        }
                    }
                    //批量插入数据
                    if (CollectionsUtil.isNotEmpty(paasMenuEntities) && paasMenuEntities.size() > 1000) {
                        paasMenuModel.insertBatch(paasMenuEntities);
                        paasMenuEntities.clear();
                    }
                    successNum++;
                } catch (XbbException e) {
                    LOG.error("公司编号为:" + corpid + "更新失败,失败理由是", e);
                    errorCorpidList.add(corpid);
                    response = new XbbResponse<>(e);
                }
            }
            //避免最后还剩余公司
            if (CollectionsUtil.isNotEmpty(paasMenuEntities)) {
                paasMenuModel.insertBatch(paasMenuEntities);
            }
            LOG.error("更新失败公司ID集合" + errorCorpidList.toString());
            LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
            LOG.warn("更新菜单表中数据操作成功,本次共更新了[{}]家公司数据", successNum);
            ScriptVO scriptVO = new ScriptVO();
            scriptVO.setMsg("成功");
            response = new XbbResponse<>(scriptVO);
        }
        return JSON.toJSONString(response);
    }


    /**
     * 删除所有公司知识库删除了，知识条目未删除的数据
     * @param productDTO
     * @param bindingResult
     * @return
     * @throws XbbException
     */
    @RequestMapping(value = "/deleteKnowledgeBase", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String deleteKnowledgeBase(@RequestBody @Valid ProductDTO productDTO, BindingResult bindingResult) throws XbbException {
        XbbResponse<ScriptVO> response;
        if (!proBaseConfig.getXbbCode().equals(productDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        if (bindingResult.hasErrors()) {
            String errMsg = Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            LOG.warn("----------------开始刷数据，将知识库删除，知识条目没删除的数据也删除掉 -------------------");
            long start = DateTimeUtil.getInt();
            // 如果没传公司ID就取所有有知识条目的公司id
            List<String> corpidList = CollectionUtils.isNotEmpty(productDTO.getCorpidList()) ? productDTO.getCorpidList() : knowledgeDataModel.getCorpidList();
            int i = 1;
            for (String corpid : corpidList) {
                LOG.warn("----------------开始刷数据{}/{}", i, corpidList.size());
                i++;
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put(StringConstant.CORPID, corpid);
                param.put(StringConstant.DEL, DelEnum.DELETE.getDel());
                List<KnowledgeBaseEntity> baseEntityList = knowledgeBaseModel.findEntitys(param);
                if (CollectionsUtil.isEmpty(baseEntityList)) {
                    continue;
                }
                List<Long> knowledgeList = baseEntityList.stream().map(e -> e.getId()).collect(Collectors.toList());
                List<Long> dataId = knowledgeDataModel.getIdListByCorpId(corpid, knowledgeList);
                knowledgeBaseHelp.deleteKnowledgeBaseByDataId(corpid, dataId);
            }
            ScriptVO scriptVO = new ScriptVO();
            scriptVO.setMsg("成功");
            LOG.warn("----------------将知识库删除后，知识条目也删除操作成功。耗时：{} -------------------", DateTimeUtil.getInt() - start);
            response = new XbbResponse<>(scriptVO);
        }
        return JSON.toJSONString(response);
    }

    /**
     * 将所有有知识条目的数据中有附件的内容，这些内容添加到附件统计表中
     * @param productDTO
     * @param bindingResult
     * @return
     * @throws XbbException
     */
    @RequestMapping(value = "/sync/knowledgeBaseFile", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String deleteKnowledgeBas1e(@RequestBody @Valid ProductDTO productDTO, BindingResult bindingResult) throws XbbException {
        XbbResponse<ScriptVO> response;
        if (!proBaseConfig.getXbbCode().equals(productDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        if (bindingResult.hasErrors()) {
            String errMsg = Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            LOG.warn("----------------开始刷数据，将知识条目中有附件 -------------------");
            long start = DateUtil.getInt();
            // 如果没传公司ID就取所有公司
            List<String> corpidList = CollectionUtils.isNotEmpty(productDTO.getCorpidList()) ? productDTO.getCorpidList() : knowledgeDataModel.getCorpidList();
            LOG.warn("----------------开始刷数据，这些公司需要刷 -------------------",corpidList);
            for (String corpid : corpidList) {
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put(StringConstant.CORPID, corpid);
                param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
                Integer count = knowledgeDataModel.getEntitysCount(param);
                if (count == 0) {
                    continue;
                }
                List<CabinetFileEntity> cabinetFileEntityList = new ArrayList<>();
                LOG.warn("----------------公司id开始刷数据：{},数据量： {}-------------------",corpid,count);
                param.put(StringConstant.COLUMNS, " id,appendix,update_id ");
                int pageNum = 1000;
                int size = count % pageNum > 0 ? count / pageNum + 1 : count / pageNum;
                for (int i = 0; i < size; i++) {
                    int page = i * pageNum;
                    param.put("start", page);
                    if (count < pageNum) {
                        param.put("pageNum", count);
                    } else {
                        param.put("pageNum", pageNum);
                    }
                    List<KnowledgeDataEntity> knowledgeDataEntityList = knowledgeDataModel.findEntitys(param);
                    if (CollectionsUtil.isEmpty(knowledgeDataEntityList)) {
                        continue;
                    }
                    List<Long> dataIdList = new ArrayList<>();
                    for (KnowledgeDataEntity knowledgeDataEntity : knowledgeDataEntityList) {
                        String appendix = knowledgeDataEntity.getAppendix();
                        if (StringUtil.isEmpty(appendix)) {
                            continue;
                        }
                        List<PaasAttachmentEntityExt> paasAttachmentEntityExts = JSONArray.parseArray(appendix, PaasAttachmentEntityExt.class);
                        if (CollectionsUtil.isEmpty(paasAttachmentEntityExts)) {
                            continue;
                        }

                        CabinetFileEntity cabinetFileEntity = insertCabinetFile(corpid, knowledgeDataEntity.getUpdateId(), knowledgeDataEntity.getId(), paasAttachmentEntityExts.get(0));
                        // 可能有脏数据，兼容一下
                        if (StringUtil.isEmpty(cabinetFileEntity.getAttachIndex())){
                            LOG.warn("出现脏数据，dataId为",knowledgeDataEntity.getId());
                            continue;
                        }
                        if (StringUtil.isEmpty(cabinetFileEntity.getExt())){
                            continue;
                        }
                        if (Objects.isNull(cabinetFileEntity.getSize())){
                            continue;
                        }
                        LOG.warn("进入到更新数据的方法",cabinetFileEntity);
                        cabinetFileEntityList.add(cabinetFileEntity);
                        dataIdList.add(knowledgeDataEntity.getId());
                    }
                    // 防止重复刷数据。
                    List<Long> cabinetFilesByIdIn = cabinetFileModel.getCabinetFileIdsByIdIn(corpid, dataIdList, XbbRefTypeEnum.KNOWLEDGE_BASE.getCode());
                    if (CollectionsUtil.isNotEmpty(cabinetFilesByIdIn) && CollectionsUtil.isNotEmpty(cabinetFileEntityList)) {
                        cabinetFileEntityList.removeIf(e -> cabinetFilesByIdIn.contains(e.getDataId()));
                    }
                }
                LOG.warn("公司id：{}，最终实际更新的数据",corpid,cabinetFileEntityList);
                if (CollectionsUtil.isEmpty(cabinetFileEntityList)) {
                    continue;
                }
                cabinetFileModel.insertBatch(cabinetFileEntityList);
            }
            ScriptVO scriptVO = new ScriptVO();
            scriptVO.setMsg("成功");
            LOG.warn("----------------知识库附件插入附件用量统计表成功，耗时 -------------------",DateUtil.getInt()-start);
            response = new XbbResponse<>(scriptVO);
        }
        return JSON.toJSONString(response);
    }


    private CabinetFileEntity insertCabinetFile(String corpid, String userId, Long id, PaasAttachmentEntityExt paasAttachmentEntityExt) throws XbbException {
        CabinetFileEntity cabinetFileEntity = new CabinetFileEntity();
        cabinetFileEntity.setCorpid(corpid);
        cabinetFileEntity.setUserId(userId);
        cabinetFileEntity.setBusinessType(XbbRefTypeEnum.KNOWLEDGE_BASE.getCode());
        cabinetFileEntity.setDataId(id);
        cabinetFileEntity.setFilename(paasAttachmentEntityExt.getFilename());
        cabinetFileEntity.setAttachIndex(paasAttachmentEntityExt.getAttachIndex());
        cabinetFileEntity.setExt(paasAttachmentEntityExt.getExt());
        cabinetFileEntity.setSize(paasAttachmentEntityExt.getSize());
        cabinetFileEntity.setType(1);
        return cabinetFileEntity;
    }
    /**
     * 待系列菜单默认值
     *
     * @param paasMenuEntity
     * @return
     */
    public PaasMenuEntity setDefaultValue(PaasMenuEntity paasMenuEntity) throws XbbException {
        PaasMenuEntity paasMenu = new PaasMenuEntity();
        paasMenu.setCorpid(paasMenuEntity.getCorpid());
        paasMenu.setAppId(paasMenuEntity.getAppId());
        paasMenu.setParentId(paasMenuEntity.getParentId());
        paasMenu.setType(MenuTypeEnum.MENU.getType());
        paasMenu.setSaasMark(paasMenuEntity.getSaasMark());
        //设置成未启用
        paasMenu.setEnable(0);
        paasMenu.setCreatorId(paasMenuEntity.getCreatorId());
        paasMenu.setAddTime(DateTimeUtil.getInt());
        paasMenu.setUpdateTime(DateTimeUtil.getInt());
        paasMenu.setDel(paasMenuEntity.getDel());
        paasMenu.setDistributorMark(paasMenuEntity.getDistributorMark());
        return paasMenu;
    }
}
